package com.farm.iproject.service.impl;

import com.farm.iproject.domain.Doctext;
import com.farm.iproject.domain.Field;
import com.farm.iproject.domain.Pdocument;
import com.farm.iproject.domain.Virtualfield;
import com.farm.core.time.TimeTool;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import com.farm.iproject.dao.DoctextDaoInter;
import com.farm.iproject.dao.PdocumentDaoInter;
import com.farm.iproject.service.DoctextServiceInter;
import com.farm.iproject.service.FieldServiceInter;
import com.farm.iproject.service.PdocumentServiceInter;
import com.farm.iproject.service.ProjectServiceInter;
import com.farm.iproject.service.VirtualfieldServiceInter;
import com.farm.iproject.utils.JsonUtils;
import com.farm.sfile.utils.FarmDocFiles;
import com.farm.util.web.HtmlUtils;
import com.farm.wsch.index.WschIndexServerInter;
import com.farm.wsch.index.WschIndexServerInter.DefaultField;
import com.farm.wsch.index.pojo.IndexDocument;
import com.farm.core.sql.query.DBRule;
import com.farm.core.sql.query.DBRuleList;
import com.farm.core.sql.query.DataQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import javax.annotation.Resource;

import com.alibaba.fastjson.JSON;
import com.farm.core.auth.domain.LoginUser;

/* *
 *功能：业务文档服务层实现类
 *详细：
 *
 *版本：v0.1
 *作者：FarmCode代码工程
 *日期：20150707114057
 *说明：
 */
@Service
public class PdocumentServiceImpl implements PdocumentServiceInter {
	@Resource
	private ProjectServiceInter projectServiceImpl;
	@Resource
	private PdocumentDaoInter pdocumentDaoImpl;
	@Resource
	private FieldServiceInter fieldServiceImpl;
	@Resource
	private DoctextServiceInter docTextServiceImpl;
	@Resource
	private DoctextDaoInter doctextDaoImpl;
	@Resource
	private VirtualfieldServiceInter virtualFieldServiceImpl;
	private static final Logger log = Logger.getLogger(PdocumentServiceImpl.class);

	@Override
	@Transactional
	public void delDocument(String projectid, String appid, LoginUser user, boolean isDelIndex) throws IOException {
		List<Pdocument> docs = pdocumentDaoImpl.selectEntitys(DBRuleList.getInstance()
				.add(new DBRule("APPID", appid, "=")).add(new DBRule("PROJECTID", projectid, "=")).toList());
		for (Pdocument doc : docs) {
			deletePdocumentEntity(doc.getId(), user, isDelIndex);
		}
	}

	@Override
	@Transactional
	public void deletePdocumentEntity(String id, LoginUser user, boolean isDelIndex) throws IOException {
		Pdocument doc = pdocumentDaoImpl.getEntity(id);
		String textid = doc.getTextid();
		pdocumentDaoImpl.deleteEntity(doc);
		docTextServiceImpl.deleteDoctextEntity(textid, user);
		if (isDelIndex) {
			synchronized (WschIndexServerInter.class) {
				WschIndexServerInter indexServer = null;
				try {
					indexServer = projectServiceImpl.getWschIndexServer(doc.getProjectid());
					indexServer.delDocument(doc.getAppid());
				} finally {
					indexServer.closeAndSubmit();
				}
			}
		}
	}

	@Override
	@Transactional
	public Pdocument getPdocumentEntity(String id) {
		if (id == null) {
			return null;
		}
		return pdocumentDaoImpl.getEntity(id);
	}

	@Override
	@Transactional
	public DataQuery createPdocumentSimpleQuery(DataQuery query) {
		DataQuery dbQuery = DataQuery.init(query,
				"WSCH_P_DOCUMENT a left join WSCH_P_PROJECT b on a.projectid=b.id left join ALONE_AUTH_USER c on a.cuser=c.id",
				"a.ID as ID,a.APPID as APPID,a.TASKKEY as TASKKEY,a.APPKEYID as APPKEYID,b.id as PROJECTID,b.name as PROJECTNAME,c.name as USERNAME,a.PSTATE as PSTATE,a.PCONTENT as PCONTENT,a.CUSER as CUSER,a.CTIME as CTIME");
		return dbQuery;
	}

	@Override
	@Transactional
	public Pdocument submitDocument(String projectid, String taskkey, Map<String, String> paras, LoginUser currentUser)
			throws IOException {
		Pdocument pdocument = new Pdocument();
		{
			Map<String, Field> fieldDic = fieldServiceImpl.getProjectFields(projectid);
			Doctext doctext = docTextServiceImpl.insertText(paras, fieldDic, projectid, currentUser);
			pdocument.setTextid(doctext.getId());
		}
		// 先在删除重复索引
		delDocument(projectid, paras.get(DefaultField.APPID.name()), currentUser, false);
		pdocument.setAppid(paras.get("APPID"));
		pdocument.setAppkeyid(paras.get("APPKEYID"));
		String popkeys = paras.get(WschIndexServerInter.DefaultField.POPKEYS.getKey());
		if (StringUtils.isBlank(popkeys)) {
			popkeys = "ALLABLE";
		}
		pdocument.setPopkeys(popkeys);
		pdocument.setCtime(TimeTool.getTimeDate14());
		pdocument.setCuser(currentUser.getId());
		pdocument.setProjectid(projectid);
		pdocument.setPstate("1");
		pdocument.setTaskkey(taskkey);
		Pdocument doc = pdocumentDaoImpl.insertEntity(pdocument);
		return doc;
	}

	@Override
	@Transactional
	public void runIndex(String taskkey, String projectid) throws IOException {
		if (StringUtils.isBlank(taskkey)) {
			throw new RuntimeException("the taskkey is null!");
		}
		List<Pdocument> docs = pdocumentDaoImpl
				.selectEntitys(DBRuleList.getInstance().add(new DBRule("TASKKEY", taskkey, "=")).toList());
		synchronized (WschIndexServerInter.class) {
			WschIndexServerInter indexServer = null;
			try {
				indexServer = projectServiceImpl.getWschIndexServer(projectid);
				int n = 0;
				for (Pdocument pdoc : docs) {
					n++;
					System.out.println(n + "/" + docs.size());
					try {
						Map<String, Object> map = docTextServiceImpl.getDocMap(pdoc, false);
						IndexDocument idoc = fieldServiceImpl.getIndexDocument(pdoc.getProjectid(), pdoc.getAppkeyid(),
								map);
						indexServer.updateDocument(idoc);
						pdoc.setPstate("3");
						pdocumentDaoImpl.editEntity(pdoc);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			} finally {
				indexServer.closeAndSubmit();
			}
		}
	}

	@Override
	@Transactional
	public Pdocument getDocument(String appid, String projectid) {
		List<Pdocument> docs = pdocumentDaoImpl.selectEntitys(DBRuleList.getInstance()
				.add(new DBRule("APPID", appid, "=")).add(new DBRule("PROJECTID", projectid, "=")).toList());
		if (docs.size() > 0) {
			return docs.get(0);
		}
		return null;
	}

	@Override
	@Transactional
	public void runIndexBySingle(String taskkey, String projectid) throws IOException {
		if (StringUtils.isBlank(taskkey)) {
			throw new RuntimeException("the taskkey is null!");
		}
		List<Pdocument> docs = pdocumentDaoImpl
				.selectEntitys(DBRuleList.getInstance().add(new DBRule("TASKKEY", taskkey, "=")).toList());
		synchronized (WschIndexServerInter.class) {
			int n = 0;
			for (Pdocument pdoc : docs) {
				n++;
				System.out.println(n + "/" + docs.size());
				WschIndexServerInter indexServer = null;
				try {
					indexServer = projectServiceImpl.getWschIndexServer(projectid);
					try {
						Map<String, Object> map = docTextServiceImpl.getDocMap(pdoc, false);
						IndexDocument idoc = fieldServiceImpl.getIndexDocument(pdoc.getProjectid(), pdoc.getAppkeyid(),
								map);
						indexServer.updateDocument(idoc);
						pdoc.setPstate("3");
						pdocumentDaoImpl.editEntity(pdoc);
					} catch (IOException e) {
						e.printStackTrace();
					}
				} finally {
					indexServer.closeAndSubmit();
				}
			}
		}
	}

	@Override
	@Transactional
	public Map<String, Object> getDocMap(Pdocument document) {
		return docTextServiceImpl.getDocMap(document, false);
	}

	@Override
	@Transactional
	public Map<String, Object> getDocumentInfo(Pdocument document) throws Exception {
		Map<String, List<Virtualfield>> virtualField = virtualFieldServiceImpl
				.getAllVirtualField(document.getProjectid());
		Map<String, Object> maps = docTextServiceImpl.getDocMap(document, true);
		Map<String, Field> fieldmap = fieldServiceImpl.getProjectFields(document.getProjectid());
		// ------------------------------------------------------
		Map<String, Object> omaps = new HashMap<>();
		for (Map.Entry<String, Object> node : maps.entrySet()) {
			String key = node.getKey();
			Object val = node.getValue();
			// 1文本2HTML
			if (fieldmap.get(key) == null) {
				throw new RuntimeException("索引" + document.getAppid() + "发现无效字段[" + key + "]未在检索项目中注册");
			}
			if (fieldmap.get(key).getTexttype().equals("2")) {
				try {
					Document dochtml = Jsoup.parse((String) val);
					Elements bodys = dochtml.getElementsByTag("body");
					if (bodys.size() > 0) {
						val = bodys.get(0).html();
					} else {
						val = dochtml.toString();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			omaps.put(key, val);
			omaps.put(key + "_HL", val);
		}
		virtualFieldServiceImpl.initVirtualField(omaps, virtualField);
		return omaps;
	}

	@Override
	@Transactional
	public void deleteAllIndex(String projectid, String appkeyid, LoginUser currentUser) throws IOException {
		synchronized (WschIndexServerInter.class) {
			WschIndexServerInter indexServer = null;
			try {
				indexServer = projectServiceImpl.getWschIndexServer(projectid);
				if (StringUtils.isNotBlank(appkeyid)) {
					indexServer.delAppDocuments(appkeyid);
				} else {
					indexServer.delAllIndex();
				}
			} finally {
				indexServer.closeAndSubmit();
			}
		}

	}
}
